/*
    REDLISP - interpreter/compiler for new dialect of LISP called REDLISP
    Copyright (C) 2006  Rudolf Olah

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef TYPES_H
#define TYPES_H

#include "defs.h"
#include <crisscross/universal_include.h>

#ifdef BIGNUM
#include <gmp.h>
#include <gmpxx.h>
#else
#include "rational.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sstream>
#include <iostream>
#include <stdarg.h>
#include <limits.h>

#ifdef TARGET_OS_WINDOWS
#include <windows.h>
#else
#define _popen popen
#define _pclose pclose
#define _stricmp strcasecmp
#include <dlfcn.h>
#endif

using namespace std;

/***************************
 * NUMBER CLASS
 ***************************/
class dNumber : public dObject
{
 public:
#ifdef BIGNUM
  mpf_class *decimal;
  mpz_class *integer;
  mpq_class *rational;

  dNumber (mpf_class var);                   // Decimal constructor
  dNumber (mpz_class var);                   // Integer constructor
  dNumber (mpq_class var);                   // Rational constructor
  dNumber (mpz_class top, mpz_class bottom); // Rational constructor

  mpf_class Decimal ();
  mpz_class Integer ();
  mpq_class Rational ();
#else
  dRational *rational;
  dNumber (dRational var); // Rational constructor

  dRational Rational ();
  double Decimal ();
  int Integer ();
#endif
  int *regularInteger;
  double *regularDecimal;
  dNumber (double var);     // Decimal constructor
  dNumber (int var);        // Integer constructor
  dNumber (int top, int bottom); // Rational constructor

  dNumber (string r); // Rational constructor
  ~dNumber ();
  string toString ();

  bool operator== (dNumber &compareTo);
  bool operator< (dNumber &compareTo);
  bool operator> (dNumber &compareTo);
};

/***************************
 * LIST CLASSES
 ***************************/
class dNode
{
 public:
  dObject *car;
  dNode *cdr;

  dNode (dObject *data, dNode *next=0);
  ~dNode ();
};

class dList : public dObject
{
 public:
  int size;
  dNode *first;
  dNode *last;

  dList ();
  dList (dNode *startNode);
  dList (dObject *startData);
  ~dList ();

  void append (dObject *data);
  void append (dNode *var);
  void insert (dObject *data);
  void insert (dNode *var);
  bool empty ();
  string toString ();
  dObject *operator[] (int index);
};

/***************************
 * FUNCTION CLASSES
 ***************************/
class dLambda : public dObject
{
 public:
  dString *doc;
  dList *local_env;
  dList *variables;
  dList *form;

  dLambda (dList *vars, dList *body, dString *docString=0);
  ~dLambda ();
  dObject *exec (dList *args, dList *env);
  string toString ();
};

class dCompiled : public dObject
{
 public:
  dObject *(*functionPointer) (dList *);

  dCompiled (dObject *(*functionPointer) (dList *));
  ~dCompiled ();
  dObject *exec (dList *args);
  string toString ();
};

/***************************
 * MODULE CLASS
 ***************************/
class dModule : public dObject
{
 public:
  string path;
  #ifdef _WIN32
  HMODULE module;
  #else
  void *module;
  #endif
  dModule (string path);
  ~dModule ();
  void unload ();
  string toString ();
};

/***************************
 * ERROR CLASS
 ***************************/
class dError : public dObject
{
 public:
  string msg, function;
  int lineNumber;
  dList *args;

  dError (string msg="", string function="", int lineNumber=-1, dList *args=0);
  dError (string msg, string function, dList *args);
  ~dError ();
  string toString ();
};

extern dSymbol *T;
extern dList *nil;
#include "core.h"

#endif
